#include "box/box_network.hh"
#include "box/service_box.hh"
#include "detail/lang_impl.hh"
#include "detail/service_logger_impl.hh"
#include "detail/stack_trace_linux.hh"
#include "detail/stack_trace_windows.hh"

#include <cassert>

auto __box_assert(kratos::service::ServiceBox *box, const char *file_name,
                  int file_line, const char *expr) -> void {

  if (!box || !file_name || !expr) {
    return;
  }
  auto stack_trace = kratos::util::StackTrace::get_stack_frame_info();
  box->write_log(kratos::lang::LangID::LANG_ASSERTION_FAIL,
                 klogger::Logger::FATAL, expr, file_name, file_line,
                 stack_trace.c_str());
}

auto __box_assert(kratos::service::ServiceLogger *service_logger,
                  const char *file_name, int file_line, const char *expr)
    -> void {
#ifndef DISABLE_SB_LOG

  using namespace kratos::service;
  using namespace kratos::lang;
  using namespace kratos::util;

  if (!service_logger || !file_name || !expr) {
    return;
  }

  auto stack_trace = StackTrace::get_stack_frame_info();

  auto *srv_logger_impl = dynamic_cast<ServiceLoggerImpl *>(service_logger);
  if (!srv_logger_impl) {
    return;
  }

  auto *box = srv_logger_impl->get_box();
  if (!box) {
    return;
  }

  auto *lang_impl = dynamic_cast<LangImpl *>(box->get_lang());
  if (!lang_impl) {
    return;
  }

  const auto *ctx_log =
      lang_impl->printf_lang(kratos::lang::LangID::LANG_SERVICE_ASSERTION_FAIL,
                             expr, file_name, file_line, stack_trace.c_str());

  if (ctx_log) {
    srv_logger_impl->fatal() << ctx_log;
  }
#endif
}

auto __box_assert(kratos::service::BoxNetwork *box_network,
                  const char *file_name, int file_line, const char *expr)
    -> void {
#ifndef DISABLE_SB_LOG
  using namespace kratos::service;
  using namespace kratos::lang;
  using namespace kratos::util;

  if (!box_network || !file_name || !expr) {
    return;
  }

  auto *lang_ptr = box_network->get_lang();
  auto *lang_impl = dynamic_cast<LangImpl *>(lang_ptr);
  if (!lang_impl) {
    return;
  }

  auto stack_trace = StackTrace::get_stack_frame_info();
  const auto *ctx_log =
      lang_impl->printf_lang(kratos::lang::LangID::LANG_ASSERTION_FAIL, expr,
                             file_name, file_line, stack_trace.c_str());

  if (!box_network->get_logger_appender()) {
    return;
  }

  box_network->get_logger_appender()->write(klogger::Logger::FATAL, "%s",
                                            ctx_log);
#endif
}
